package com.ea.holder;

import com.alibaba.fastjson.JSONObject;
import com.ea.common.constant.RedisKeyConstants;
import com.ea.common.enums.ResponseStatusEnums;
import com.ea.common.enums.TypeStatusEnums;
import com.ea.common.response.JsonResult;
import com.ea.common.util.RedisUtil;
import com.ea.common.util.TokenUtil;
import com.ea.domain.entity.AdminInfo;
import com.ea.domain.entity.UserInfo;
import com.ea.mapper.AdminInfoMapper;
import com.ea.mapper.UserInfoMapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author NAME-L
 * @Description TODO
 * @className RequestHandlerIntercept
 * @date 2023-01-15 19:52:54
 */
@Configuration
public class RequestHandlerInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(RequestHandlerInterceptor.class);

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private AdminInfoMapper adminInfoMapper;

    /**
     * 前端发起请求，后端处理请求前的前置操作
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        logger.info("url=========>{}" , request.getRequestURI());
        // 从请求头中获取token
        String userToken = request.getHeader("tokenFront");
        String adminToken = request.getHeader("tokenBack");
        String token = "";
        String type = "";
        if (StringUtils.isNotEmpty(userToken) || StringUtils.isNotEmpty(adminToken)) {
            token = StringUtils.isNotEmpty(userToken) ? userToken : adminToken;
            type = StringUtils.isNotEmpty(userToken) ? "user" : "admin";
        }
        // 如果token为空或者token校验失败
        //todo toekn自动延期
//        if (StringUtils.isEmpty(token) || !TokenUtil.verify(token)) {
        if (StringUtils.isEmpty(token)) {
            try {
                logger.error("用户鉴权失败，无法访问");
                response.setCharacterEncoding("UTF-8");
                response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                response.setStatus(Integer.parseInt(ResponseStatusEnums.NOT_ALLOW.getCode()));
                response.setHeader("Access-Control-Allow-Credentials", "true");
                response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
                response.getOutputStream().write(JsonResult.withoutData(ResponseStatusEnums.NOT_ALLOW.getCode(), "用户鉴权失败，无法访问").toString().getBytes());
                response.getOutputStream().close();
            } catch (Exception e) {
                logger.error("request login token error:{}", e.getMessage());
            }
            return false;
        }
        Long userId = TokenUtil.getUserId(token);
        boolean exists = false;
        if (TypeStatusEnums.ADMIN.getCode().equals(type)) {
            exists = redisUtil.hasKey(RedisKeyConstants.SUBJECT_KEY + userId + RedisKeyConstants.ADMIN_LOGIN_TOKEN);
        } else if (TypeStatusEnums.USER.getCode().equals(type)) {
            exists = redisUtil.hasKey(RedisKeyConstants.SUBJECT_KEY + userId + RedisKeyConstants.USER_LOGIN_TOKEN);
        }
        // 如果token在redis中不存在那么需要重新登录
        if (!exists) {
            try {
                response.setCharacterEncoding("UTF-8");
                response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                response.setHeader("Access-Control-Allow-Credentials", "true");
                response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
                response.setStatus(Integer.parseInt(ResponseStatusEnums.NOT_ALLOW.getCode()));
                JSONObject returnJson = new JSONObject();
                returnJson.put("errorCode", ResponseStatusEnums.NOT_ALLOW.getCode());
                returnJson.put("errorMsg", "用户登录验证失败，请重新登录");
                response.getOutputStream().write(returnJson.toString().getBytes());
                response.getOutputStream().close();
            } catch (Exception e) {
                logger.error("request login token error:{}", e.getMessage());
            }
            return false;
        }
        if (TypeStatusEnums.ADMIN.getCode().equals(type)) {
            //存在则进行token过期时间刷新
            redisUtil.expire(RedisKeyConstants.SUBJECT_KEY + userId + RedisKeyConstants.ADMIN_LOGIN_TOKEN, 60 * 20);
            AdminInfo adminInfo = adminInfoMapper.selectAdminInfoByAdminId(userId);
            AdminHolderInfo.setAdminInfo(adminInfo);
        } else {
            //存在则进行token过期时间刷新
            redisUtil.expire(RedisKeyConstants.SUBJECT_KEY + userId + RedisKeyConstants.USER_LOGIN_TOKEN, 60 * 20);
            UserInfo userInfo = userInfoMapper.selectUserByUserId(userId);
            UserHolderInfo.setUserInfo(userInfo);
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserHolderInfo.clearUserCache();
    }
}
